存储单元-触发器、锁存器、寄存器
//部分知识点来源于大佬 孤独的单刀
触发器:
触发器是边沿敏感的存储单元,数据存储的动作由某一信号的上升或者下降沿进行同步的。触发器是计算机记忆装置的基本单元,一个触发器能储存一位二进制代码
锁存器:锁存器是电平触发的存储单元,数据存储的动作取决于使能信号的电平值,当锁存器处于使能状态时,输出才会随着数据输入发生变化。(简单地说,它有两个输入,分别是一个有效信号EN,一个输入数据信号DATA_IN,它有一个输出Q,它的功能就是在EN有效的时候把DATA_IN的值传给Q,也就是锁存的过程)。
寄存器:一个触发器可以组成一个一位的寄存器,多个触发器可以组成一个多位的寄存器。存储器是由大量寄存器组成的,其中每一个寄存器就称为一个存储单元。它可以存放一个有独立意义的二进制代码。
7系列FPGA一个CLB含有两个SLICE,每个SLICE含有8个触发器或锁存器,其中4个只能为触发器,4个可以作为触发器也可以作为锁存器。但是作为锁存器时,其余4个触发器将不能在使用。
通过对复位方式、复位电平参数的配置,可以将D触发器约定为下述4种基本组成情况:
- 异步复位(FDCE)
- 异步置位(FDPE)
- 同步复位(FDRE)
- 同步置位(FDSE)
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
4个DFF会映射到2个不同的SLICE里边,而不再同一个SLICE中的原因?
时钟使能信号CE、时钟信号CLOCK和置位/复位信号SR是DFF的控制信号,它们的一组值构成DFF的一个控制集。在同一个SLICE中,必须保证所有DFF的控制集是相同的。
在上述Verilog代码中,4个DFF根据控制集的不同,可以分为2类:异步类与同步类(SR区分),所以在FPGA实现时,会把这两类DFF分别映射到2个SLICE里去。
在Xilinx器件的代码中,一般建议使用高电平复位,如果使用低电平复位则需要在前面加个LUT6作为反相器有点浪费资源,而Altera的底层逻辑则是低电平复位有效。当然了,我一般是不建议你使用复位的,除非是一些没办法的控制逻辑。这可以参考:FPGA的复位设计要醒目点啦
锁存器
从寄存数据的角度来讲,触发和锁存器的功能是相同的;它们的区别在于触发是同步时钟控制,而锁存器是电位信号控制。触发器是指有时钟边沿触发的存储单元。锁存器指一个由信号而不是时钟控制的电平敏感的设备。
锁存器的工作原理:锁存器不同于触发器,锁存器在不锁存数据时,输出端的信号随输入信号变化,就像信号通过一个缓存器一样;一旦锁存信号起锁存作用,则数据被锁住,输入信号不起作用。因此锁存器也称为透明锁存器,值得是不锁存是输出对输入是透明的。
锁存器具备下列缺点:
对毛刺敏感,不能异步复位,因此在上电后处于不确定的状态。 锁存器会使静态时序分析变得非常复杂,不具备可重用性。(首先, 锁存器没有时钟参与信号传递,无法做 STA;其次,综合工具会将 latch 优化掉,造成前后仿真结果不一致)
会出现锁存器的情况:
- 不完整的组合逻辑语句always块中if-else语句不完整
- 不完整的组合逻辑语句always块中case语句不完整
MUX多路选择器
7系列一个slice里面包括4个LUT6,3个2选1选择器,一个进位链carry4,8个FF(4个纯FF,4个FF/lanch)
7系列一个LUT6可以实现4选一的多路选择器
2个LUT6加上一个MUXF7可以实现(5-8)选一的多路选择器
4个LUT6 + 2个MUXF7 + 1个MUXF8 可以实现一个16选一的多路选择器
若大于16路的多路选择器则需要数个SLICE的资源进行级联来实现
MUX2是可以用LUT6来实现的,也就是说 2个LUT6 + 1个MUXF7可以转换成2个LUT6 + 1个LUT6来实现MUX8;
而4个LUT6 + 2个MUXF7+1个MUXF8可以转换成4个LUT6 + 1个LUT6来实现。那么既然LUT6可以实现MUX2的功能,FPGA里为何还要有固定的MUX这种结构?
首先可以肯定的是用LUT6来实现MUX2的效率没有固定MUX2的效率高,因为有两个输入没有利用就意味着有资源是浪费的。其次,每个SLICE中只有4个LUT6,如果只用LUT6来实现MUX16则需要5个LUT6,那么第5个LUT6则势必会布线到其他Slice,这样就容易造成不好布线和拥堵,且4个LUT6的输出分别到达第五个LUT6的时间会不同,到达时间不一致则容易产生毛刺。