FPGA基础知识极简教程(5)什么是锁存器以及如何在FPGA开发中避免生成锁存器?

举报
李锐博恩 发表于 2021/07/15 01:33:35 2021/07/15
【摘要】 博文目录 写在前面正文什么是D锁存器?锁存器是如何生成的?如何避免生成锁存器? 参考资料交个朋友 写在前面 个人微信公众号: FPGA LAB个人博客首页注:学习交流使用! 本文我们将讨论两个问题: 什么是锁存器?如何避免生成锁存器? 正文 在FPGA设计中永远不要使用锁存器!但好像没人在FPGA设计中故意设计锁存器,那为什么要讨论锁...


写在前面

本文我们将讨论两个问题:

  • 什么是锁存器?
  • 如何避免生成锁存器?

正文

在FPGA设计中永远不要使用锁存器!但好像没人在FPGA设计中故意设计锁存器,那为什么要讨论锁存器呢?
话虽如此,虽然你没有有意设计锁存器,但你能保证你的代码中没有锁存器了吗?
综合工具(将Verilog或VHDL代码转换为低级FPGA组件的工具)生成的常用锁存器是 门控D型锁存器。但是,还有其他类型的锁存器:SR锁存器,D锁存器,JK锁存器和Earle锁存器。这些类型的锁存器不在本文讨论范围内,如需了解,可以自行查询资料。

什么是D锁存器?

门控D锁存器有两个输入和一个输出。框图如下所示。输入D是您的数据输入。输入E是你的输入输入。仅当Enable为1时,输出Q才会获得D上的值。当Enable为0时,无论输入D在做什么,输出都不会改变,即保持。它保持其先前的值,因此为什么将其称为锁存器! 当使能为低电平时,输出被锁存。

门控D锁存器
真值表

现在,之所以建议不要使用锁存器,因为它们非常危险。 这有两个主要原因:

  • 通常,锁存器是FPGA工程师无意间生成的。 编写的HDL代码很可能不是设计人员真正想要的。
  • FPGA工具很难正确创建它们。 通常,它们会增加大量的布线延迟,并可能导致您的设计无法满足时序要求。(耗费资源)

让我们继续讨论锁存器,并讨论锁存器是如何生成的?并如何避免生成锁存器呢?

锁存器是如何生成的?

想要避免,就要了解锁存器生成的原理。只有了解它,才能对付它,也就是避免它!

在Verilog的组合always块,或者VHDL的组合process以及conditional assignment中,未给所有可能的输入分配输出,就是产生锁存器!这将创建综合工具所谓的不完全分配。
看如下VHDL代码:


library ieee;
use ieee.std_logic_1164.all;
 
entity bad_latch is
  port ( i_data   : in  std_logic; i_enable : in  std_logic; o_latch  : out std_logic );
end bad_latch;
 
architecture rtl of bad_latch is
begin process (i_data, i_enable)
  begin if i_enable = '1' then o_latch <= i_data; end if;
  end process;
 
end architecture rtl;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

或Verilog代码:

module bad_latch(
	input i_data,
	input i_enable,
	output reg o_latch
);

always@(*) begin
	if(i_enable) begin
		o_latch = i_data;
	end
end


endmodule


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

您在上面的代码中看到问题了吗?当i_enable为0时会发生什么?这是未定义的!这些工具假定,当i_enable为0时,o_latch上的值不应更改。由于这是组合逻辑(不使用时钟),因此可以推断出一个锁存器。

如下图为其RTL图:
RTL原理图

让我们再看一个创建锁存器的VHDL示例。

library ieee;
use ieee.std_logic_1164.all;
 
entity bad_latch_2 is
  port ( i_select : in  std_logic_vector(1 downto 0); o_latch  : out std_logic_vector(3 downto 0) );
end bad_latch_2;
 
architecture rtl of bad_latch_2 is
begin -- Incomplete Assignment:
  o_latch <= "0101" when i_select = "00" else "0111" when i_select = "01" else "1111" when i_select = "10"; -- Fixed!
  -- o_latch <= "0101" when i_select = "00" else
  -- "0111" when i_select = "01" else -- "1111" when i_select = "10" else -- (others => '0');
 
end architecture rtl;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

或Verilog表达为:

module bad_latch2(
	input [1:0] i_select,
	output reg [3:0] o_latch
);

always@(*) begin
	case(i_select)
		2'b00: begin o_latch = 4'b0101;
		end
		2'b01: begin o_latch = 4'b0111;
		end
		2'b10: begin o_latch = 4'b1111;
		end

	endcase
end


endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

我们忘记指定i_select的所有可能的输入组合。当i_select =“ 11”时,o_latch会发生什么?这会导致分配不完整,因此会产生锁存器。
如下图:

锁存器生成

锁存器几乎肯定不是数字设计师打算用此代码创建的。要修复上面的代码,数字设计师可以指定当i_select =“ 11”时发生的情况,或者可以在不附加任何条件的情况下使用else子句。我推荐后者,因为它更灵活。如果i_select的宽度从两位变为三位,您的代码仍不会创建锁存器。让我们看一下Verilog中的另一个示例:

module no_latch2(
	input [1:0] i_select,
	output reg [3:0] o_latch
);

always@(*) begin
	case(i_select)
		2'b00: begin o_latch = 4'b0101;
		end
		2'b01: begin o_latch = 4'b0111;
		end
		2'b10: begin o_latch = 4'b1111;
		end
		default: begin o_latch = 4'b0000;
		end

	endcase
end


endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

此时就不会生成锁存器!
如下图:

不会生成锁存器情况

如何避免生成锁存器?

经过上面的讨论,我们知道了组合逻辑中如果未给所有可能的输入分配输出,就是产生锁存器!
需要注意的是一定是组合逻辑才会产生锁存器,时序逻辑永远不会!
既然我们知道了产生锁存器的原因,我们自然知道如何规范代码,为所有可能的输入分配输出,适当地在case中使用default以及在if中使用else并分配输出值,就可以避免这种情况。


参考资料


交个朋友

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/106679147

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。