HDLBits 系列(2)如何避免生成锁存器?

目录

抛砖引玉

实际测试


抛砖引玉

从一个小例子引入设计:

我们需要设计一个电路,要实现的功能是,如果电脑CPU过热,则电脑关机;

你可能想到的伪代码是这样的:

  • If (cpu_overheated) then shut_off_computer = 1;

可以,是对功能的描述。

但是存在一个情况就是其他情况呢?

如果默认不写回事会有什么问题?

答案也很简单,默认不写,就相当于保持输出原来的状态:

HDLBits 系列(2)如何避免生成锁存器?_第1张图片

而组合逻辑中,这种“保持输出不变”的行为意味着需要记住当前状态,从而产生一个锁存器。组合逻辑(例如逻辑门)无法记住任何状态。组合电路必须在所有情况下都为所有输出分配一个值。这通常意味着您 始终需要else子句或分配给输出的默认值。

那么正确的做法应该是:

reg shut_off_computer;

always@(*) begin

if (cpu_overheated)  shut_off_computer = 1;

else shut_off_computer = 0;

end

wire shut_off_computer;

assign shut_off_computer =  cpu_overheated ? 1 : 0;

这个例子就是所谓的避免生成锁存器的最常见的一种情况,就是组合逻辑中,要把else子句或者case的default补上,并且给出输出的默认值。

另外一个小例子,各位自己想想吧。

如果没有达到目的地,且没油了,则停止驾驶,有油的话,继续驾驶。还有一种情况呢?如果达到了,当然没必要继续驾驶了。

  • If (~arrived) then keep_driving = ~gas_tank_empty;

 

上面两个小例子的代码放到一个模块中:

// synthesis verilog_input_version verilog_2001
module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  ); //

    always @(*) begin
        if (cpu_overheated)
           shut_off_computer = 1;
        else 
            shut_off_computer = 0;
    end

    always @(*) begin
        if (~arrived)
           keep_driving = ~gas_tank_empty;
        else
           keep_driving = 0;
    end

endmodule

HDLBits 系列(2)如何避免生成锁存器?_第2张图片


实际测试

最后附上,以前的总结:

23、写出会生成锁存器的三种情况?

1)组合逻辑中,if语句缺少else,或者else内未给输出赋值;

module test (
	input [1:0] sel,
	input a,
	input b,
	input c,
	output out
);
reg out;
always@(*) begin
if(sel == 2'b00) out = a;
else if(sel == 2'b01) out = b;
else if(sel == 2'b10) out = c;
end
	
endmodule

HDLBits 系列(2)如何避免生成锁存器?_第3张图片

如果赋值了呢?

module test (
	input [1:0] sel,
	input a,
	input b,
	input c,
	input d,
	output out
);
reg out;
always@(*) begin
if(sel == 2'b00) out = a;
else if(sel == 2'b01) out = b;
else if(sel == 2'b10) out = c;
else out = d;
end
	
endmodule

HDLBits 系列(2)如何避免生成锁存器?_第4张图片

 

猜想:时序逻辑中if缺少else会怎么样?

module test (
    input clk, 
	input [1:0] sel,
	input a,
	input b,
	input c,
	//input d,
	output out
);
reg out = 0;
always@(posedge clk) begin
if(sel == 2'b00) out <= a;
else if(sel == 2'b01) out <= b;
else if(sel == 2'b10) out <= c;
//else out <= d;
end
endmodule

 

HDLBits 系列(2)如何避免生成锁存器?_第5张图片

 

时序逻辑中if不缺少else会怎么样?

module test (
    input clk, 
	input [1:0] sel,
	input a,
	input b,
	input c,
	input d,
	output out
);
reg out = 0;
always@(posedge clk) begin
if(sel == 2'b00) out <= a;
else if(sel == 2'b01) out <= b;
else if(sel == 2'b10) out <= c;
else out <= d;
end
	
endmodule

HDLBits 系列(2)如何避免生成锁存器?_第6张图片

2)组合逻辑中case缺少中情况未列全且缺少default,或者default中没有给输出赋值,或者自己赋值给自己,就会生成锁存器(Latch);

 

module test (
    //input clk, 
	input [1:0] sel,
	input a,
	input b,
	input c,
	//input d,
	output out
);
reg out = 0;
always@(*) begin
case(sel)
2'b00: out = a;
2'b01: out = b;
2'b10: out = c;
endcase
end
	
endmodule

HDLBits 系列(2)如何避免生成锁存器?_第7张图片

 

如果组合逻辑case中default没有缺少,并且给输出赋值了,会是什么样子?

module test (
    //input clk, 
	input [1:0] sel,
	input a,
	input b,
	input c,
	input d,
	output out
);
reg out;
always@(*) begin
case(sel)
2'b00: out = a;
//2'b01: out = b;
//2'b10: out = c;
//2'b11: out = d;
default: out = d;
endcase
end
	
endmodule

HDLBits 系列(2)如何避免生成锁存器?_第8张图片

3)组合逻辑中always@()块内敏感列表没有列全;

第三种情况,大概的意思就是如果敏感列表没有补全,该触发的时候没有触发,那么还不是保存了之前的输出结果,因而会生成锁存器。

 

 

 

你可能感兴趣的:(#,HDLBits)