上一篇講解了什麼是 latch,其又與 flip-flop 差在哪,也解釋了我們要去避免它的原因,那麼這篇將會告訴你有哪幾種情況會產生 latch。
在組合邏輯中,不完整的 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 具有儲存前態的功能,並只有在正負緣才會改變值~
邏輯跟 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 來當判斷元素,也可以避免。
等號右邊的所有變數或判斷元素都應蓋列入 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 生成原因以及相對應解決的方法~~