资讯详情

从底层结构开始学习FPGA(3)----存储单元之触发器、寄存器与锁存器

一、基本概念

二、FPGA内部存储单元

触发器-toc" style="margin-left:0px;">三、触发器

锁存器-toc" style="margin-left:0px;">四、锁存器


系列目录与传送门

从底层结构学习FPGA》目录及传送门


一、基本概念

:触发器是边缘敏感的存储单元,数据存储的动作是由信号的上升或下降沿同步的。触发器是计算机记忆装置的基本单元,触发器可以存储一个二进制代码。

:锁定器是电平触发的存储单元。数据存储的动作取决于能量信号的电平值。当锁定器处于能量状态时,输出会随数据输入而变化。(简单地说,它有两个输入,即有效信号EN,输入数据信号DATA_IN,它有一个输出Q,它的功能是EN有效时把DATA_IN的值传给Q,也就是锁定的过程)。

:一个触发器可以形成一个寄存器,多个触发器可以形成寄存器。存储器由大量的寄存器组成,每个寄存器都被称为存储单元。它可以存储一个独立的二进制代码。

数字电路中有两种存储单元,一种是触发器,另一种是锁定器。两者最大的区别是前者通过来改变存储的输出状态,后者是通过改变存储的输出状态。FPGA在很多情况下,我们基本上使用更多的触发器,锁定器应该避免使用,因为它不需要时钟,所以它不是时间元件,没有毛刺过滤功能,非常敏感,容易出现问题。

而我们平时所说的寄存器,基本上理解为一个或者一组FF。

二、FPGA内部存储单元

在7系列FPGA的底层----CLB、可编程逻辑块中有两个SLICE,其中每个SLICE都有8个存储单元。虽然是存储单元,但实际上是四个触发器 FF 4个触发器FF或锁存器LATCH(可配置为其中一种)。其结构如下图所示:

323179bd737f4b9981950b53fa71106c.png

左边的四个存储单元只能用作触发器,而右边的四个存储单元不仅可以用作触发器,还可以用作锁定器,但需要注意的是:一旦SLICE中(即8个FF)中的4个FF被作为LATCH使用,剩下的四个FF不能使用,会造成资源浪费。

三、触发器

在FPGA内据复位方式、复位电平和上电电平值的不同,内部触发器通常配置为D触发器。

在Verilog在语言中,我们定义了一个reg会在FPGA映射成一组或一组FF。举例如下:

module test(  input             clk,  input             rst_n,  input             in1,  output reg        A );  always@(posedge clk)begin      if(~rst_n)   A <= 1'b0;  else   A <= in1; end  endmodule

显然,在FPGA的实现就是1bit的FF:

下面的句子在FPGA实现将类推到4FF:

module test(  input             clk,  input             rst_n,  input      [3:0]  in1,  output reg [3:0]  A );  always@(posedge clk)begin      if(~rst_n)   A <= 4'd0;  else   A <= in1; end  endmodule

如果你还记得数电,你应该能看到上面配置的触发器实际上是D触发器(DFF)。D触发器可以通过配置复位模式和复位电平参数来约定以下四个基本组成:

  • 异步复位(FDCE)
  • 异步置位(FDPE)
  • 同步复位(FDRE)
  • 同步置位(FDSE)

如何使用这四种类型的D触发器?Verilog实现?接下来我们就建一个项目,看看到底,Verilog代码:

module test(  input clk,  input rst,  input in1,  input in2,  input in3,  input in4,  output reg out1,  output reg out2,  output reg out3,  output reg out4  );       // FDCE  always @ ( posedge clk or posedge rst)begin     if(rst)         out1 <= 1'b0;     else         out1 <= in1;  end    // FDPE  always @ ( posedge clk or posedge rst )begin     if(rst)         out2 <= 1'b1;     else         out2 <= in2;  end    // FDRE  always @ ( posedge clk )begin     if(rst)         out3 <= 1'b0;     else         out3 <= in3;  end    // FDSE  always @ ( posedge clk )begin     if(rst)         out4 <= 1'b1;     else         out4 <= in4;  end      endmodule 

vivado推断门级电路如下:

推断出两个同步寄存器和两个异步寄存器,其他信息暂时看不到,但与我们预期的基本一致。

vivado综合原理图:

到这一步,基本上综合了上述四种不同类型的例子DFF再来看看FPGA的映射:

这里有一个有趣的地方:四个DFF会映射到两个不同的SLICE它们在里面SLICE其实还是有空间的,那为什么呢?

时钟使信号CE、时钟信号CLOCK和位/复位信号SR是DFF它们的一组值构成的控制信号DFF控制集。在同一个SLICE一定要保证一切DFF控制集是一样的。

在上述Verilog代码中,4个DFF根据控集的不同,可以分为2类:异步类与同步类(SR区分),所以在FPGA实现时,会把这两类DFF分别映射到2个SLICE里去。

        

        在上面的部分我们还了解了DFF的一些参数如下:

  • INIT1:表示FF在上电或者全局复位时初始化值为1
  • INIT0:表示FF在上电或者全局复位时初始化值为0
  • SRHIGH:表示FF在SR置位时(即用户复位),FF的值为1
  • SRLOW:表示FF在SR置位时(即用户复位),FF的值为0

        接下来我举例来说明这几个参数究竟对应着什么:

module test(
	input	clk,
	input	rst_n,
	input	in1,
	input	in2,
	output	out1,
	output	out2
);

reg	out1_r = 1'b1;			//INIT1
reg	out2_r = 1'b0;			//INTT0

assign out1 = out1_r;
assign out2 = out2_r;

always@(posedge clk)begin    
	if(rst)
		out1_r <= 1'b1;		//SRHIGH
	else
		out1_r <= in1;
end

always@(posedge clk)begin    
	if(rst)
		out2_r <= 1'b0;		//SRLOW
	else
		out2_r <= in2;
end

endmodule

        这次我们不看图了,我们使用TCL指令:write_verilog -force test.v  来看看实现的网表。如下(截取部分有用信息):

        第1个always块的DFF被综合成立FDSE(同步置位set,即1)且上电初始值为1, 这与Verilog代码一致;第2个always块的DFF则被综合成立FDRE(同步复位reset,即0)且上电初始值为0, 同样与Verilog代码一致。

        最后要说明的是:SR默认高电平有效,所以在Xilinx器件的代码中,一般建议使用高电平复位,如果使用低电平复位则需要在前面加个LUT6作为反相器有点浪费资源,而Altera的底层逻辑则是低电平复位有效。当然了,我一般是不建议你使用复位了,除非是一些没办法的控制逻辑。可以参考:FPGA的复位设计要醒目点啦

四、锁存器

        从寄存数据的角度来讲,触发和锁存器的功能是相同的;它们的区别在于触发是同步时钟控制,而锁存器是电位信号控制。触发器是指有时钟边沿触发的存储单元。锁存器指一个由信号而不是时钟控制的电平敏感的设备。

        锁存器的工作原理:锁存器不同于触发器,锁存器在不锁存数据时,输出端的信号随输入信号变化,就像信号通过一个缓存器一样;一旦锁存信号起锁存作用,则数据被锁住,输入信号不起作用。因此锁存器也称为透明锁存器,值得是不锁存是输出对输入是透明的。

        锁存器具备下列缺点:

  • 对毛刺敏感,不能异步复位,因此在上电后处于不确定的状态。
  • 锁存器会使静态时序分析变得非常复杂,不具备可重用性。(首先, 锁存器没有时钟参与信号传递,无法做 STA;其次,综合工具会将 latch 优化掉,造成前后仿真结果不一致)

        根据锁存器的特点可以看出,在电路设计中,要对锁存器特别谨慎,如果设计经过综合后产生出和设计意图不一致的锁存器,则将导致设计错误,包括仿真和综合。因此,在设计中需要避免产生意想不到的锁存器。

        

        下列场景会产生锁存器(时序逻辑不会产生锁存器):

  • 不完整的组合逻辑语句always块中if-else语句不完整
  • 不完整的组合逻辑语句always块中case语句不完整

        举例1:if语句中缺少else

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

always@(*)begin    
	if(en)	out = in;		
	//else	out1_r = in1;	//缺少else
end

endmodule

        举例2:组合逻辑的case语句不完整:

module test(
	input			a,
	input			b,
	input	[1:0]	en,
	output	reg		out
);

always@(*)begin    
	case(en)
		2'b00:out = a;
		2'b01:out = b;
		//case语句不完整
	endcase
end

endmodule

       

        上述两种情况都是,代码缺少完整条件的描述,编译工具认为在此情况下该值保持不变,就推断出了锁存器。

        所以,为了防止锁存器的产生,在组合逻辑一定要将if-else语句、case语句描述完整,而时序逻辑则没有这个问题。        

        

标签: r09n系列电位器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台