【Day13】Latch 的生成条件以及如何避免(下)

Latch 的生成条件

上一篇讲解了什麽是 latch,其又与 flip-flop 差在哪,也解释了我们要去避免它的原因,那麽这篇将会告诉你有哪几种情况会产生 latch。


第一种:if 语句结构不完整

在组合逻辑中,不完整的 if-else 语句会导致 latch 的生成,那怎样是不完整呢?
就是最後缺少了 else,正是因为没有写 else,会被系统认定为该值不需要改变,而自动生成 latch 来帮你储存

会生成 latch 的例子:

module latch_test(
  in,
  en, 
  out
);
input  in;
input  en;
output out;
reg    out;

always@(*)begin
  if(en) out = in;//no else
end

endmodule

解决方法:

SOL1:补齐 else 语句

module latch_test(
  in,
  en, 
  out
);
input  in;
input  en;
output out;
reg    out;

always@(*)begin
  if(en) out = in;
  else   out = 1'b0;//add
end

endmodule

SOL2:在 always 内最上方加上初值

module latch_test(
  in,
  en, 
  out
);
input  in;
input  en;
output out;
reg    out;

always@(*)begin
  out = 1'b0;//initialization
  if(en) out = in;
end

endmodule

但这里有一点该注意,其实讲补齐 if-else 算是拢统的说法,因为以下这个例子其实也会产生 latch,原因就在同一个变数在不同 if 条件下都要叙述完整,否则还是会生成 latch。

module latch_test(
  in1,
  in2,
  en, 
  out1,
  out2
);
input  in1;
input  in2;
input  en;
output out1;
output out2;
reg    out1;
reg    out2;

always@(*)begin
  if(en) out1 = in1;
  else   out2 = in2;
end

endmodule

应改成

module latch_test(
  in1,
  in2,
  en, 
  out1,
  out2
);
input  in1;
input  in2;
input  en;
output out1;
output out2;
reg    out1;
reg    out2;

always@(*)begin
  if(en)begin
    out1 = in1;
    out2 = 1'b0;//add
  end 
  else begin
    out1 = 1'b0;//add
    out2 = in2;
  end 
end

endmodule

这里值得注意的是,在循序逻辑中(clock触发),不完整的 if-else 并不会生成 latch,因为 register 具有储存前态的功能,并只有在正负缘才会改变值~


第二种:case 语句结构不完整

逻辑跟 if-else 相似,就是最後缺少了 default,正是因为没有写 default,进入到未被定义的 case 时会被系统认定为该值不需要改变,而自动生成 latch 来帮你储存。

会生成 latch 的例子:

module latch_test(
  in1,
  in2,
  sel, 
  out
);
input       in1;
input       in2;
input [1:0] sel;
output      out;
reg         out;

always@(*)begin
  case(sel)
    2'd0:out = in1;
    2'd1:out = in2;
  endcase
end

endmodule

应改成

module latch_test(
  in1,
  in2,
  sel, 
  out
);
input       in1;
input [1:0] sel;
output      out;
reg         out;

always@(*)begin
  case(sel)
    2'd0:out = in1;
    2'd1:out = in2;
    default:out = 1'b0;//add
  endcase
end

endmodule

或是补上初值也是可以的!


第三种:使变数等於自己时或是判断元素有自己时

因为会用到变数的前态而自动生成 latch 来帮你储存。

会生成 latch 的例子:

reg a;
reg b;

always@(*)begin
  if(a | b)a = 1'b0;
  else     a = 1'b1;
end

以及

reg a;
reg b;
always@(*)begin
  if(b)a = a;
  else a = a + 1'b1;
end

当然 wire 也不例外

wire a;
wire c;
reg b;
assign a = (a & b)?(1'b0):(1'b1);
assign c = (a & b)?(c):(1'b0);

这种其实不太能解,就是尽量不要这样写

或是,如果输出没有非常及时,也可以延後一个 clk 将值锁在 register 内
EX:

reg a;
reg b;
reg a_temp;

always@(posedge clkSys)begin
  a_temp <= a;
end

always@(*)begin
  if(a_temp | b)a = 1'b0;
  else          a = 1'b1;
end

用先前储存的 a_temp 来当判断元素,也可以避免。


第四种:always 触发条件不完整

等号右边的所有变数或判断元素都应盖列入 alway 触发条件中

会生成 latch 的例子:

module latch_test(
  in1,
  in2,
  sel, 
  out
);
input  in1;
input  in2;
input  sel;
output out;
reg    out;

always@(in1 or in2)begin
  if(sel)out = in1;
  else   out = in2;
end

endmodule

应改成

module latch_test(
  in1,
  in2,
  sel, 
  out
);
input  in1;
input  in2;
input  sel;
output out;
reg    out;

always@(in1 or in2 or sel)begin//add sel
  if(sel)out = in1;
  else   out = in2;
end

endmodule

以上四种就是常见的 latch 生成原因以及相对应解决的方法~~


<<:  Re: 新手让网页 act 起来: Day13 - Hook Flow

>>:  Day13 - 物理模拟篇 - 弹跳球世界IV - 成为Canvas Ninja ~ 理解2D渲染的精髓

新新新手阅读 Angular 文件 - Router - pathMatch(2) - Day28

本文内容 接续,Day27 的内容,纪录阅读有关 Angular Route 的 pathMatch...

【Day19】电子商务与行销篇-营销活动

#odoo #开源系统 #数位赋能 #E化自主 企业之广告行销手法,除了透过email、UTMs、问...

EP21 - [Ruby on Rails] 新增订单

Youtube 频道:https://www.youtube.com/c/kaochenlong ...

防止使用者频繁送出 Request & 倒数计时重新发送认证码

以实务来说,总是会有一些情况导致使用者没办法正常收到认证码,所以系统必须具备 retry on fa...

新新新手阅读 Angular 文件 - pathMatch(3) - Day29

本文内容 本文内容为阅读与 Angular 的 pathMatch:full 和 redirectT...